/* Copyright (c) 2004-2024 peigen.info. All rights reserved. */

package info.peigen.hotpot.common.service.base.gateway;


import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.annotation.JSONField;
import com.google.common.collect.Maps;
import info.peigen.hotpot.common.core.enums.Symbol;
import jakarta.validation.constraints.NotEmpty;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <b>(AbstractGatewayRequest)</b>
 *
 * @author Peigen
 * @version 1.0.0
 * @since 2019-05-28
 */
@SuppressWarnings("unused")
@SuperBuilder
@Data
@NoArgsConstructor
public abstract class AbstractGatewayRequest implements GatewayRequest, Serializable {

    /** 交易码，有些渠道的不同接口是以不同的交易码来表示 */
    @NotEmpty
    protected String              transCode;
    /** 扩展参数 */
    @JSONField(serialize = false)
    @Builder.Default
    protected Map<String, Object> extend = Maps.newHashMap();

    /**
     * 获取request的Map形式
     *
     * @return map对象
     */
    @JSONField(serialize = false)
    public Map<String, String> getMapData() {
        return toTreeMap();
    }

    /**
     * 实现报文
     *
     * @return String
     */
    @JSONField(serialize = false)
    public String getDatagram() {
        return JSON.toJSONString(getMapData());
    }

    private Map<String, String> toTreeMap() {
        List<Field> fieldList = new ArrayList<>();
        Field[]     fields    = getClass().getDeclaredFields();
        if (fields.length > 0) {
            fieldList.addAll(Arrays.asList(fields));
        }

        Field[] fields2 = getClass().getSuperclass().getDeclaredFields();
        if (fields2.length > 0) {
            fieldList.addAll(Arrays.asList(fields2));
        }

        TreeMap<String, String> map = new TreeMap<>();

        for (Field field : fieldList) {
            if (!"serialVersionUID".equals(field.getName())) {
                String fldVal = getFieldValue(this, field.getName());
                if (fldVal != null) {
                    map.put(field.getName(), fldVal);
                }
            }
        }

        return map;
    }

    private String getFieldValue(Object owner, String fieldName) {
        Object obj = invokeMethod(owner, fieldName);
        return obj != null ? obj.toString() : null;
    }

    private Object invokeMethod(Object owner, String fieldName) {
        Class<?> ownerClass = owner.getClass();
        String   methodName = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
        Method   method;
        try {
            method = ownerClass.getMethod("get" + methodName);
            return method.invoke(owner);
        } catch (Exception var8) {
            return null;
        }
    }

    protected String buildParams(Map<String, String> params) {
        return params
                .entrySet()
                .stream()
                .filter(entry -> StrUtil.isNotEmpty(entry.getValue()))
                .map(entry -> entry.getKey() + Symbol.EQUALS.code() + entry.getValue())
                .collect(Collectors.joining(Symbol.AMPERSAND.code()));
    }

    private String urlEncode(String str) {
        try {
            return URLEncoder.encode(str, StandardCharsets.UTF_8);
        } catch (Throwable e) {
            return str;
        }
    }

}